# Created by 黄景涛
# DATE: 2024/11/5

import re
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException

from base.kdt_lib.base_mixin import BaseMiXin


class LocalMiXin(BaseMiXin):

    # 内置，按字段的父表单定位
    def _location_by_parent(self, form_loc: str, field_name: str):
        """
        :param self:
        :param form_loc: 字段所在的父表单
        :param field_name: 字段名称
        :return:
        """
        form = self.driver.find_element(By.XPATH, form_loc)
        # 适配1：itsm-3.x版本的工单字段
        ticket_v3_fields = form.find_elements(By.XPATH, './/div[contains(@class, "bk-form-item")]')
        # 适配2：itsm-4.x版本的工单字段
        ticket_v4_fields = form.find_elements(By.XPATH, './/div[contains(@class, "field-form-item")]')
        # 适配3：itsm-4.x版本的dialog表单字段
        dialog_fields = form.find_elements(By.XPATH, './/div[contains(@class, "bk-form-item")]')
        # 还可以添加其他适配...
        fields = ticket_v4_fields or dialog_fields or ticket_v3_fields

        for field in fields:
            if field_name in field.text:
                # 为了处理小部分表单项，需要精确到文本域（剔除字段label后的部分）
                loc_area_types = ['.//div[@class="field-form-content"]', './/div[@class="bk-form-content"]']
                for loc_area in loc_area_types:
                    try:
                        area_field = field.find_element(By.XPATH, loc_area)
                        return area_field
                    except NoSuchElementException:
                        continue
                raise NoSuchElementException('所有定位方式都没有定位到字段的输入框！')

        raise Exception(f'不存在字段【{field_name}】')

    # 内置，按字段label名称定位
    def _location_by_name(self, field_label_name: str):
        """
        :param self:
        :param field_label_name: 字段的label名称
        :return:
        """
        span_name_loc = '//label[@class="field-label"]/div/span'
        spans = self.driver.find_elements(By.XPATH, span_name_loc)
        target_span = None
        for s in spans:
            if field_label_name in s.text:
                target_span = s
                break

        if target_span is None:
            raise Exception(f'未找到名称为【{field_label_name}】的字段！')

        # 向上找 “div>label>div>span” span的父标签
        label = target_span.find_element(By.XPATH, './ancestor::label[1]')
        field = label.find_element(By.XPATH, './parent::div')
        return field

    # 内置，按普通方式定位字段
    def _location_by_loc(self, loc):
        """
        :param self:
        :param loc: 定位参数
        :return:
        """
        return self.find_element(loc)

    def located_field(self, type_args):
        """
        字段定位统一入口
        :param type_args: 定位参数, 包含定位方式、参数
        :return: WebElement对象
        """
        # 正则匹配逗号，但忽略在方括号内的逗号
        pattern = re.compile(r',\s*(?![^\[]*])')
        # 正则分割
        loc_type, *args = pattern.split(type_args.replace('，', ','))
        loc_function_name = '_location_' + loc_type.strip()

        try:
            location_function = getattr(self, loc_function_name)
        except AttributeError as e:
            raise Exception(f'loc_type参数错误, {self.__class__.__name__}中找不到【{loc_function_name}】,e: {e}')

        field = location_function(*args)
        self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", field)  # 元素滚动到视图的正中间
        return field

